home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / screen-resolution-extra / screenresolution-mechanism.py < prev    next >
Text File  |  2009-10-08  |  11KB  |  290 lines

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright (C) 2008 Fluendo Embedded S.L. (www.fluendo.com)
  5. #
  6. # This program is free software; you can redistribute it and/or modify it under
  7. # the terms of the GNU General Public License as published by the Free Software
  8. # Foundation; either version 2 of the License, or (at your option) any later
  9. # version.
  10. #
  11. # This program is distributed in the hope that it will be useful, but WITHOUT
  12. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13. # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  14. # details.
  15. #
  16. # You should have received a copy of the GNU General Public License along with
  17. # this program; if not, write to the Free Software Foundation, Inc.,
  18. # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  19. #
  20. # taken from:
  21. # https://code.fluendo.com/remotecontrol/trac/browser/trunk/
  22. #         gnome_lirc_properties/backend.py?rev=217
  23. # modified by Harald Hoyer <harald@redhat.com>
  24. #
  25. # modified by Alberto Milone (tseliot) <albertomilone@alice.it>
  26.  
  27. import dbus, dbus.service, gobject, logging
  28. import os, os.path
  29. import sys
  30. from XKit import xutils, xorgparser
  31. import time
  32. import shutil
  33. import subprocess
  34.  
  35. # Modern flavors of dbus bindings have that symbol in dbus.lowlevel,
  36. # for old flavours the internal _dbus_bindings module must be used.
  37.  
  38. try:
  39.     # pylint: disable-msg=E0611
  40.     from dbus.lowlevel import HANDLER_RESULT_NOT_YET_HANDLED
  41.  
  42. except ImportError:
  43.     from _dbus_bindings import HANDLER_RESULT_NOT_YET_HANDLED
  44.  
  45. class AccessDeniedException(dbus.DBusException):
  46.     '''This exception is raised when some operation is not permitted.'''
  47.  
  48.     _dbus_error_name = 'com.ubuntu.screenresolution.Mechanism.AccessDeniedException'
  49.  
  50. class UnsupportedException(dbus.DBusException):
  51.     '''This exception is raised when some operation is not supported.'''
  52.  
  53.     _dbus_error_name = 'com.ubuntu.screenresolution.Mechanism.UnsupportedException'
  54.  
  55. class UsageError(dbus.DBusException):
  56.     '''This exception is raised when some operation was not used properly.'''
  57.  
  58.     _dbus_error_name = 'com.ubuntu.screenresolution.Mechanism.UsageError'
  59.  
  60. class PolicyKitService(dbus.service.Object):
  61.     '''A D-BUS service that uses PolicyKit for authorization.'''
  62.  
  63.     def _check_permission(self, sender, conn, action, reconnect=True):
  64.         '''
  65.         Verifies if the specified action is permitted, and raises
  66.         an AccessDeniedException if not.
  67.         '''
  68.         if sender is None and conn is None:
  69.             # called locally, not through D-BUS
  70.             return
  71.  
  72.         # get peer PID
  73.         dbus_info = dbus.Interface(conn.get_object('org.freedesktop.DBus',
  74.               '/org/freedesktop/DBus/Bus', False), 'org.freedesktop.DBus')
  75.         pid = dbus_info.GetConnectionUnixProcessID(sender)
  76.  
  77.         # query PolicyKit
  78.         polkit = dbus.Interface(get_service_bus().get_object(
  79.                 'org.freedesktop.PolicyKit1',
  80.                 '/org/freedesktop/PolicyKit1/Authority', False),
  81.                 'org.freedesktop.PolicyKit1.Authority')
  82.         try:
  83.             # we don't need is_challenge return here, since we call with AllowUserInteraction
  84.             (is_auth, _, details) = polkit.CheckAuthorization(
  85.                     ('unix-process', {'pid': dbus.UInt32(pid, variant_level=1)}),
  86.                     action, {'': ''}, dbus.UInt32(1), '', timeout=600)
  87.         except dbus.DBusException, e:
  88.             if reconnect and e._dbus_error_name == 'org.freedesktop.DBus.Error.ServiceUnknown':
  89.                 # polkitd timed out, connect again
  90.                 return self._check_polkit_privilege(sender, conn, action, reconnect=False)
  91.             else:
  92.                 raise
  93.  
  94.         if not is_auth:
  95.             logging.debug('_check_permission: sender %s on connection %s pid %i is not authorized for %s: %s' %
  96.                     (sender, conn, pid, action, str(details)))
  97.             raise AccessDeniedException(action)
  98.  
  99.  
  100. class BackendService(PolicyKitService):
  101.     '''A D-Bus service that PolicyKit controls access to.'''
  102.  
  103.     # pylint: disable-msg=C0103,E0602
  104.  
  105.     INTERFACE_NAME = 'com.ubuntu.ScreenResolution.Mechanism'
  106.     SERVICE_NAME   = 'com.ubuntu.ScreenResolution.Mechanism'
  107.     IDLE_TIMEOUT   =  30
  108.  
  109.     def __init__(self, connection=None, path='/'):        
  110.         if connection is None:
  111.             connection = get_service_bus()
  112.  
  113.         super(BackendService, self).__init__(connection, path)
  114.  
  115.         self.__name = dbus.service.BusName(self.SERVICE_NAME, connection)
  116.         self.__loop = gobject.MainLoop()
  117.         self.__timeout = 0
  118.         connection.add_message_filter(self.__message_filter)
  119.  
  120.     def __message_filter(self, connection, message):
  121.         '''
  122.         D-BUS message filter that keeps the service alive,
  123.         as long as it receives message.
  124.         '''
  125.  
  126.         if self.__timeout:
  127.             self.__start_idle_timeout()
  128.  
  129.         return HANDLER_RESULT_NOT_YET_HANDLED
  130.  
  131.     def __start_idle_timeout(self):
  132.         '''Restarts the timeout for terminating the service when idle.'''
  133.  
  134.         if self.__timeout:
  135.             gobject.source_remove(self.__timeout)
  136.  
  137.         self.__timeout = gobject.timeout_add(self.IDLE_TIMEOUT * 1000,
  138.                                              self.__timeout_cb)
  139.  
  140.     def __timeout_cb(self):
  141.         '''Timeout callback that terminates the service when idle.'''
  142.  
  143.         # Keep service alive, as long as additional objects are exported:
  144.         if self.connection.list_exported_child_objects('/'):
  145.             return True
  146.  
  147.         print 'Terminating %s due to inactivity.' % self.SERVICE_NAME
  148.         self.__loop.quit()
  149.  
  150.         return False
  151.  
  152.     def run(self):
  153.         '''Creates a GLib main loop for keeping the service alive.'''
  154.  
  155.         print 'Running %s.' % self.SERVICE_NAME
  156.         print ('Terminating it after %d seconds of inactivity.' 
  157.                % self.IDLE_TIMEOUT)
  158.  
  159.         self.__start_idle_timeout()
  160.         self.__loop.run()
  161.  
  162.  
  163.     # pylint: disable-msg=R0913
  164.     @dbus.service.method(dbus_interface=INTERFACE_NAME,
  165.                          in_signature='as', out_signature='b',
  166.                          sender_keyword='sender', connection_keyword='conn')   
  167.     def setVirtual(self, virtres, sender=None, conn=None):
  168.         '''
  169.         Replace the first line of this example with a source and a destination file
  170.         '''
  171.         self._check_permission(sender, conn,
  172.             'com.ubuntu.screenresolution.mechanism.configure')
  173.  
  174.         virtual = ' '.join(virtres)
  175.         
  176.         source = '/etc/X11/xorg.conf'
  177.         destination = '/etc/X11/xorg.conf'
  178.         
  179.         if os.path.exists(source):
  180.             #make a backup of the xorg.conf
  181.             backup = source + "." + time.strftime("%Y%m%d%H%M%S")
  182.             shutil.copyfile(source, backup)
  183.         
  184.         try:
  185.             a = xutils.XUtils(source)
  186.         except(IOError, xorgparser.ParseException):#if xorg.conf is missing or broken
  187.             a = xutils.XUtils()#start from scratch
  188.         
  189.         empty = True
  190.         for section in a.globaldict:
  191.             if len(a.globaldict[section]) > 0:
  192.                 empty = False
  193.                 break
  194.  
  195.         if empty:
  196.             a.makeSection('Device', 'Configured Video Device')
  197.             a.makeSection('Screen', identifier='Configured Screen Device')
  198.             a.addReference('Screen', 'Device', 'Configured Video Device', position=0)
  199.             a.makeSubSection('Screen', 'Display', position=0)
  200.             a.addSubOption('Screen', 'Display', 'Virtual', value=virtual, position=0)
  201.         
  202.         else:#if xorg.conf exists and is not empty
  203.             devicelen = len(a.globaldict['Device'])
  204.             screenlen = len(a.globaldict['Screen'])
  205.             
  206.             if screenlen == 0:
  207.                 screen = a.makeSection('Screen', identifier='Configured Screen Device')
  208.                 if devicelen == 0:
  209.                     device = a.makeSection('Device', 'Configured Video Device')
  210.                 else:
  211.                     device = 0
  212.                 a.addReference('Screen', 'Device', 'Configured Video Device', position=device)
  213.                 
  214.                 a.makeSubSection('Screen', 'Display', position=0)
  215.                 a.addSubOption('Screen', 'Display', 'Virtual', value=virtual, position=0)
  216.                 
  217.             else:#if at least 1 Screen section exists
  218.                 '''
  219.                 Set the virtual section in all the Screen sections
  220.                 '''
  221.                 for screen in a.globaldict['Screen']:
  222.                     a.makeSubSection('Screen', 'Display', position=screen)
  223.                     a.addSubOption('Screen', 'Display', 'Virtual', value=virtual, position=screen)
  224.  
  225.         '''
  226.         Write the changes to the destination file
  227.         '''
  228.         a.writeFile(destination)
  229.         return True
  230.     
  231.     @dbus.service.method(dbus_interface=INTERFACE_NAME,
  232.                          in_signature='s', out_signature='i',
  233.                          sender_keyword='sender', connection_keyword='conn')
  234.     def setDontZap(self, enable, sender=None, conn=None):
  235.         '''Try to set the DontZap option in the xorg.conf
  236.            and return the exit code of dontzap'''
  237.  
  238.         self._check_permission(sender, conn,
  239.             'com.ubuntu.screenresolution.mechanism.dontzap')
  240.  
  241.         dontzap_file = '/usr/bin/dontzap'
  242.         if not os.path.isfile(dontzap_file):
  243.             logging.error('/usr/bin/dontzap does not exist')
  244.             return 1
  245.         
  246.         if enable in ['--enable', '--disable']:
  247.             logging.debug('calling dontzap with %s' % enable)
  248.             retcode = subprocess.call([dontzap_file, enable])
  249.             return retcode
  250.         else:
  251.             logging.error('called with wrong arguments = %s' % enable)
  252.             return 1
  253.     
  254.     
  255. def get_service_bus():
  256.     '''Retrieves a reference to the D-BUS system bus.'''
  257.  
  258.     return dbus.SystemBus()
  259.  
  260. def get_service(bus=None):
  261.     '''Retrieves a reference to the D-BUS driven configuration service.'''
  262.  
  263.     if not bus:
  264.         bus = get_service_bus()
  265.  
  266.     service = bus.get_object(BackendService.SERVICE_NAME, '/')
  267.     service = dbus.Interface(service, BackendService.INTERFACE_NAME)
  268.  
  269.     return service
  270.  
  271. if __name__ == '__main__':
  272.     # Support full tracing when --debug switch is passed:
  273.     import sys
  274.     from sys import argv
  275.  
  276.     # Integrate DBus with GLib main loops.
  277.  
  278.     from dbus.mainloop.glib import DBusGMainLoop
  279.     DBusGMainLoop(set_as_default=True)
  280.  
  281.     # Run the service.
  282.  
  283.     if '--debug' in argv or '-d' in argv:
  284.         logging.basicConfig(stream=sys.stderr)
  285.         logging.getLogger().setLevel(logging.NOTSET)
  286.         
  287.     BackendService().run()
  288.  
  289.